<template>
	<div class="tree">
		<el-tree
			:allow-drag="allowDrag"
			:data="tree"
			:expand-on-click-node="false"
			@node-drag-end="nodeDrop"
			default-expand-all
			draggable
			highlight-current
			node-key="id"
			ref="tree"
			v-on="listeners"
			v-show="tree.length"
		>
			<div class="custom-tree-node" slot-scope="{  data }">
				<div class="name-warp">
					<i class="el-icon-folder"></i>
					<span class="name" v-if="!data.edit">{{ data.folderName }}({{data.counts}})</span>
					<el-input class="name" clearable maxlength="10" placeholder="文件夹名最多10字" v-else v-model.trim="data.newName"></el-input>
				</div>
				<div class="icon" v-if="data.id===allParentId">
					<i @click.stop="addFile(data)" class="el-icon-folder-add" title="添加文件夹"></i>
				</div>
				<div class="icon" v-else>
					<template v-if="!data.edit">
						<i @click.stop="addFile(data)" class="el-icon-folder-add" title="添加文件夹"></i>
						<i @click.stop="editFileloader(data)" class="el-icon-edit" title="编辑文件夹"></i>
						<el-popconfirm
							:title="`${data.children&&data.children.length?'该文件夹下还有子文件夹，删除该文件夹会导致子文件夹被一起删除，':''}是否删除${data.folderName}文件夹？`"
							@confirm="dlFolders(data)"
							cancel-button-text="取消"
							confirm-button-text="确定"
							icon="el-icon-info"
							icon-color="red"
						>
							<i class="el-icon-delete" slot="reference" title="删除文件夹"></i>
						</el-popconfirm>
						<i class="el-icon-rank" title="移动文件夹"></i>
					</template>
					<template v-else>
						<i class="el-icon-loading" v-if="data.loading"></i>
						<template v-else>
							<i @click.stop="changeName(data)" class="success el-icon-success" title="确认操作"></i>
							<i @click.stop="cancel(data)" class="el-icon-error" title="取消操作"></i>
						</template>
					</template>
				</div>
			</div>
		</el-tree>

		<div class="nodata" v-show="!tree.length">
			<Empty>
				暂无文件夹，点击
				<a @click="addFolder" href="javascript:void(0);">添加</a>
			</Empty>
		</div>
	</div>
</template>
<script>
import _ from 'lodash'
import Empty from '@components/common/Empty'
function setEdit(data) {
	data.forEach(el => {
		el.edit = false
		el.loading = false
		el.newName = el.folderName
		if (el.children && el.children.length) {
			setEdit(el.children)
		}
	})
	return data
}
const addMap = new Map()
const allParentId = 9999999
export default {
	props: {
		/**
		 * 获取数据的方法
		 */
		getTreeFunction: {
			required: true,
			type: Function
		},
		/**
		 * 编辑文件夹的方法
		 * @returns {String} 新增文件夹时需后端返回一个文件夹id
		 */

		editFunction: Function,
		/**
		 * 删除文件夹的方法
		 */
		deleteFolder: Function
	},
	components: {
		Empty
	},
	watch: {
		// treeData(val) {
		// 	this.tree = setEdit(_.cloneDeep(val))
		// }
		// tree(val){
		// 	if(val.length===1&&val[0].id === 99999){
		// 		this.tree
		// 	}
		// }
	},
	computed: {
		listeners() {
			return {
				...this.$listeners,
				'node-click': this.nodeClick
			}
		}
	},
	data() {
		return {
			allParentId,
			tree: []
		}
	},
	created() {
		this.getTreeData()
	},
	methods: {
		nodeClick(val) {
			if (val.edit) return
			if (val.id === allParentId) {
				this.$emit('node-click', {
					...val,
					id: ''
				})
			} else {
				/**
				 * @description 点击文件夹触发
				 * @event nodeClick
				 * @type {Event}
				 */
				this.$emit('node-click', val)
			}
		},
		getRefs() {
			return this.$refs.tree
		},
		async getTreeData() {
			const res = await this.getTreeFunction()
			const all = [
				{
					folderName: '全部目录',
					id: allParentId,
					counts: 0,
					children: []
				}
			]
			if (res.length) {
				const counts = res.reduce((num, el) => {
					return num + el.counts
				}, 0)

				all[0].children = setEdit(res)
				all[0].counts = counts
				// this.tree = all
				// this.$nextTick(() => {
				// 	this.$refs.tree.setCurrentKey(99999)
				// })
				// this.oldTree = _.cloneDeep(all)
				this.tree = all
				this.$nextTick(() => {
					this.$refs.tree.setCurrentKey(allParentId)
				})
				this.oldTree = _.cloneDeep(all)
			} else {
				this.tree = []
			}
		},
		addFolder() {
			const all = [
				{
					folderName: '全部目录',
					id: allParentId,
					counts: 0,
					children: []
				}
			]
			this.addFile(all[0])
			this.tree = all
			this.oldTree = _.cloneDeep(all)
		},
		editFileloader(data) {
			data.newName = data.folderName
			data.edit = true
			console.log(data)
		},
		async changeName(data) {
			if (data.newName === '') {
				return this.$message.error('文件夹名称不能为空')
			}
			data.loading = true
			try {
				const floderId = await this.editFunction({
					...data,
					id: data.id || null,
					parentId: data.parentId === allParentId || data.parentId === 0 ? null : data.parentId,
					folderName: data.newName
				})
				if (!data.id) {
					data.loading = false
					data.folderName = data.newName
					data.edit = false
					data.id = floderId
					data.counts = 0
					console.log(data)
					// this.getTreeData()
				} else {
					data.loading = false
					data.folderName = data.newName
					data.edit = false
				}
			} catch (error) {
				data.loading = false
				data.newName = data.folderName
			}
		},
		async dlFolders(data) {
			await this.deleteFolder(data)
			this.$message.success('删除成功')
			this.getTreeData()
		},
		addFile(data) {
			// 将添加了文件夹的父文件夹保持到addMap里
			if (!addMap.has(data.id)) {
				addMap.set(data.id, data)
			}
			if (!data.children) {
				data.children = []
			}
			data.children.push({
				addId: new Date() * 1,
				newName: '',
				edit: true,
				folderName: '',
				parentId: data.id
			})
		},
		cancel(data) {
			data.edit = false
			if (!data.id) {
				// 删除当前未提交的文件夹
				const addObj = addMap.get(data.parentId)
				addObj.children = addObj.children.filter(el => {
					return !(el.addId && el.addId === data.addId)
				})

				// 检查添加列表内是否还有未完成填加的文件夹，没有就将父文件夹从addMap里删除
				const hasAdd = addObj.children.some(item => item.addId)
				if (!hasAdd) {
					addMap.delete(data.parentId)
				}

				// 如果是最上级全部目录，则删除整个
				if (addObj.children.length === 0 && addObj.id === allParentId) {
					this.tree = []
					this.oldTree = []
				}
			}
		},
		nodeDrop(draggingNode, dropNode, dropType, ev) {
			if (dropType !== 'none') {
				console.log(draggingNode, dropNode, dropType, ev)
				const type = {
					before: '前',
					after: '后',
					inner: '内'
				}
				this.$confirm(`是否要将'${draggingNode.data.folderName}'移动到'${dropNode.data.folderName}'文件夹${type[dropType]}`, '提示', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					type: 'warning'
				})
					.then(async () => {
						try {
							await this.editFunction({
								id: draggingNode.data.id,
								folderName: draggingNode.data.folderName,
								parentId: dropNode.data.id
							})
							this.$message.success('移动成功')
						} catch (error) {
							this.tree = _.cloneDeep(this.oldTree)
						}
					})
					.catch(() => {
						this.tree = _.cloneDeep(this.oldTree)
					})
			}
		},
		allowDrag(draggingNode) {
			return draggingNode.data.id !== -1
		}
	}
}
</script>
<style lang="scss" scoped>
.tree {
	.custom-tree-node {
		align-content: center;
		font-size: 14px;
		line-height: 28px;
		flex: 1;
		position: relative;
		:v-deep .el-input__suffix {
			i {
				height: 24px;
				line-height: 24px;
			}
		}
		:v-deep .el-input__inner {
			height: 24px;
			line-height: 24px;
			display: inline-block;
		}

		.name-warp {
			margin-right: 76px;
			.name {
				margin-left: 5px;
			}
		}
		.icon {
			position: absolute;
			right: 0;
			top: 0;
			i {
				margin-left: 5px;
			}
			.success {
				color: $color-success !important;
			}
			.warn {
				color: $color-warn !important;
			}
			.err {
				color: $color-err !important;
			}
			.info {
				color: $color-info !important;
			}
		}
	}
	.nodata {
		height: 400px;
	}
}
</style>
